package middleware

import (
	"context"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"tapay-bot/global"
	"tapay-bot/pkg/app"
	"tapay-bot/pkg/convert"
	"tapay-bot/pkg/errcode"
	"tapay-bot/pkg/redis"
)

func JWT() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			ecode = errcode.Success
			cliam *app.Claims
		)
		if s, exist := c.GetQuery("token"); exist {
			token = s
		} else {
			token = c.GetHeader("token")
			//log.Println(token)
		}
		if token == "" {
			ecode = errcode.UnauthorizedTokenError
		} else {
			var err error
			cliam, err = app.ParseToken(token)
			if err != nil {
				switch err.(*jwt.ValidationError).Errors {
				case jwt.ValidationErrorExpired:
					ecode = errcode.UnauthorizedTokenTimeout
				default:
					ecode = errcode.UnauthorizedTokenError
				}
			}
		}

		if ecode != errcode.Success {
			response := app.NewResponse(c)
			response.ToErrorResponse(ecode)
			//c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
			c.Abort()
			return
		}

		//防止卡商id与用户id冲突
		var userCacheToken = getUserCacheToken(cliam)
		if userCacheToken != token {
			response := app.NewResponse(c)
			response.ToErrorResponse(errcode.UnauthorizedTokenTimeout)
			c.Abort()
			return
		}
		c.Set("userID", cliam.UserID)
		c.Set("userRole", cliam.UserRole)
		c.Set("nickname", cliam.Nickname)
		c.Next()
	}
}

func getUserCacheToken(cliam *app.Claims) string {
	userType := global.UserType(convert.StrTo(cliam.UserRole).MustInt())
	ctx := context.Background()
	switch userType {
	case global.UserTypeCarder:
		return redis.Get(ctx, fmt.Sprintf("user_token_kadmin:%d", cliam.UserID))
	case global.UserTypeTpAgent, global.UserTypeAdmin:
		return redis.Get(ctx, fmt.Sprintf("login_token:%d", cliam.UserID))
	default:
		return redis.Get(ctx, fmt.Sprintf("user_token:%d", cliam.UserID))
	}
}

func JWTAdmin() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			ecode = errcode.Success
			cliam *app.Claims
		)
		if s, exist := c.GetQuery("token"); exist {
			token = s
		} else {
			token = c.GetHeader("token")
			//log.Println(token)
		}
		if token == "" {
			ecode = errcode.UnauthorizedTokenError
		} else {
			var err error
			cliam, err = app.ParseToken(token)
			if err != nil {
				switch err.(*jwt.ValidationError).Errors {
				case jwt.ValidationErrorExpired:
					ecode = errcode.UnauthorizedTokenTimeout
				default:
					ecode = errcode.UnauthorizedTokenError
				}
			}
		}

		if ecode != errcode.Success {
			response := app.NewResponse(c)
			response.ToErrorResponse(ecode)
			c.Abort()
			return

		}
		//log.Println("jwt middle ware userid", cliam.UserID)
		adminKey := fmt.Sprintf("login_token:%d", cliam.UserID)
		adminCacheToken := redis.Get(c, adminKey)
		if adminCacheToken != "" && adminCacheToken != token {
			response := app.NewResponse(c)
			response.ToErrorResponse(errcode.UnauthorizedTokenTimeout)
			c.Abort()
			return
		}
		c.Set("userID", cliam.UserID)
		c.Set("userRole", cliam.UserRole)
		c.Set("nickname", cliam.Nickname)
		c.Next()
	}
}

func ImportJWT() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			cliam *app.Claims
		)
		if s, exist := c.GetQuery("token"); exist {
			token = s
		} else {
			token = c.GetHeader("token")
		}
		if token != "" {
			var err error
			cliam, err = app.ParseToken(token)
			if err == nil {
				//log.Println("jwt middle ware userid", cliam.UserID)
				c.Set("userID", cliam.UserID)
				c.Set("userRole", cliam.UserRole)
				c.Set("nickname", cliam.Nickname)
			}
		}
		c.Next()
	}
}

func ImportJWTWithoutValid() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			cliam *app.Claims
		)
		if s, exist := c.GetQuery("token"); exist {
			token = s
		} else {
			token = c.GetHeader("token")
		}
		if token != "" {
			var err error
			cliam, err = app.ParseTokenWithoutValid(token)
			if err == nil {
				//log.Println("jwt middle ware userid", cliam.UserID)
				c.Set("userID", cliam.UserID)
				c.Set("userRole", cliam.UserRole)
				c.Set("nickname", cliam.Nickname)
			}
		}
		c.Next()
	}
}
